package com.maimao.websocket.server;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.log.Log;
import cn.hutool.log.LogFactory;
import com.maimao.core.utils.DateUtils;
import com.maimao.model.goods.enums.GoodsCheckEnum;
import com.maimao.model.goods.log.GoodsCheck;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 商品推送需求： 后台负责审核商品的管理员登录后作为客户端连接到webSocket服务端， 商品发布/修改 --->  调用该端口  ---> 按照负载均衡策略发送消息到客户端 客户端收到消息后 刷新待审核信息；
 *
 * @author MaoLin Wang
 * @date 2021/3/21 9:38 下午
 */
@Component
@ServerEndpoint("/websocket/goods/{userId}")
public class GoodsWebSocketServer {
    private static int onlineCount = 0;

    private static Log log = LogFactory.get(GoodsWebSocketServer.class);



    /**
     * 管理员id -- > websocket实例
     */
    private static ConcurrentHashMap<String, GoodsWebSocketServer> socketMap = MapUtil.newConcurrentHashMap(10);
    ;
    /**
     * 与客户端的连接会话
     */
    private Session session;

    private String userId;

    /**
     * 连接建立成功的回调
     */
    @OnOpen
    public void onOpen(Session session, @PathParam("userId") String userId) {
        this.session = session;
        this.userId = userId;
        if (socketMap.containsKey(userId)) {
            socketMap.remove(userId);
            socketMap.put(userId, this);
        } else {
            socketMap.put(userId, this);
            addCount();
        }

        log.info("客户端id：{}连接 ,当前连接数：{}", userId, getOnlineCount());


    }

    /**
     * 连接关闭调用的方法
     */
    @OnClose
    public void onClose() {
        if (socketMap.containsKey(userId)) {
            socketMap.remove(userId);
            //从set中删除
            decrease();
        }
        log.info("客户端:{} 断开连接，当前连接数为：{}", this.userId, getOnlineCount());
    }

    /**
     * 接收客户端消息
     *
     * @param message
     * @param session
     */
    @OnMessage
    public void onMessage(String message, Session session) {
        log.info("收到客户端:{}的消息：{}", this.userId, message);
        //暂时不需要接收消息
    }


    /**
     * 按照随机策略给在线客户端发送消息 消息记录在es中，为待处理，前端管理员审核操作完成后，更新消息为已处理
     */
    public static String sendInfo(String goodsId) throws IOException {
        log.info("prepare to send msg:{} , to clients", goodsId);
        if (!socketMap.isEmpty()) {
            /**
             *  1.ES中当前goodsId有未处理的审核记录，失效处理，添加新的记录，sendMsg
             *  2.ES中没有当前goodsId未审核记录，直接添加，sendMsg
             */
            String clientId = (String) RandomUtil.randomEle(socketMap.keySet().toArray());
            if (!StrUtil.isBlank(clientId)) {
                GoodsWebSocketServer server = socketMap.get(clientId);
                if (!ObjectUtil.isEmpty(server)) {
                    server.sendMessage(goodsId);
                }
            }
            return clientId;

        }
        return null;
    }



    /**
     * 服务端主动推送消息
     */
    private void sendMessage(String message) throws IOException {
        this.session.getBasicRemote().sendText(message);
    }

    private static synchronized int getOnlineCount() {
        return GoodsWebSocketServer.onlineCount;
    }


    private static synchronized void decrease() {
        GoodsWebSocketServer.onlineCount--;
    }

    private static synchronized void addCount() {
        GoodsWebSocketServer.onlineCount++;
    }

}
